package org.fastsyncer.core;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.common.entity.ScheduleJob;
import org.fastsyncer.core.service.PluginService;
import org.fastsyncer.core.service.impl.DriverEventServiceImpl;
import org.fastsyncer.manager.framework.DataFactory;
import org.fastsyncer.manager.listener.ListenerFactory;
import org.fastsyncer.manager.monitor.HeartBeatJob;
import org.fastsyncer.manager.scheduler.SchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component("ContextListener")
public class ContextListener implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger logger = LoggerFactory.getLogger("Application Server Context");

    @Autowired
    private PluginService plugin;

    @Autowired
    private DriverEventServiceImpl event;

    private DataFactory data = DataFactory.getInstance();

    private ListenerFactory listener = ListenerFactory.getInstance();

    private SchedulerFactory scheduler = SchedulerFactory.getInstance();

    /**
     * 当spring上下文加载完毕后执行
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent e) {
        if (null == e.getApplicationContext().getParent()) {
            this.init();
        }
    }

    private void init() {
        logger.info("ServerContext initialization started.\r");

        // DataFactory >> PluginService >> DriverEventService >> ListenerFactory >> SchedulerFactory
        // 1.加载驱动历史配置
        data.start();
        // 2.加载插件
        plugin.start();
        // 3.加载驱动监听
        event.start();
        // 4.加载驱动增量监听器
        listener.start();

        /** 格式: [秒] [分] [小时] [日] [月] [周] [年]
        0 0 12 * * ?                每天12点执行
        0 15 10 ? * *               每天的10:15执行
        0 15 10 * * ?               每天的10:15执行
        0 15 10 * * ? *             每天的10:15执行
        0 15 10 * * ? 2005          2005年每天的10:15执行
        0 * 14 * * ?                每天的14:00到14:59期间每分钟执行
        0 0/5 14 * * ?              每天的14:00到14:55每隔5分钟执行
        0 0/5 14,18 * * ?           每天的14:00到14:55每隔5分钟执行和18:00到18:55每隔5分钟执行
        0 0-5 14 * * ?              每天的14:00到14:05执行
        0 10,44 14 ? 3 WED          三月的每一个周三的14:10和14:44执行
        0 15 10 ? * MON-FRI         工作日每天的10:15:00执行
        0 15 10 15 * ?              每个月的第15天的10:15:00执行
        0 15 10 L * ?               每个月最后一天的10:15:00执行
        0 15 10 ? * 6L              每个月最后一个周五的10:15:00执行
        0 15 10 ? * 6L 2002-2005    2002, 2003, 2004, 和2005年每个月最后一个周五的10:15:00执行
        0 15 10 ? * 6#3             每个月的第三个周五的10:15:00执行
        0 0 12 1/5 * ?              每个月的第一天的12:00:00开始执行，每隔5天间隔执行
        0 11 11 11 11 ?             每年的11月11日11:11:00执行 
        */
        List<ScheduleJob> jobs = new ArrayList<ScheduleJob>();
        // 监听驱动可用性,默认每隔20秒
        Class<?> heart = HeartBeatJob.class;
        jobs.add(new ScheduleJob().setJobId(heart.getName()).setCronExpression("*/20 * * * * ? *").setJobClass(heart));
        // 获取历史驱动定时任务
        Map<String, Object> mappings = data.getMappings();
        for (Map.Entry<String, Object> entry : mappings.entrySet()) {
            MappingTask task = (MappingTask) entry.getValue();
            // 1.是否满足驱动定时任务条件
            if (!scheduler.validateEnabled(task)) {
                continue;
            }
            // 2.创建定时任务job
            ScheduleJob scheduleJob = scheduler.createScheduleJob(task);
            if (null != scheduleJob) {
                jobs.add(scheduleJob);
            }
        }

        // 5.启动定时调度实例
        scheduler.start(jobs);
        logger.info("ServerContext initialization completed.\r");
    }

}
